package com.cmw.auntapp.core.base;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.cmw.auntapp.constant.BaseAPI;
import com.cmw.auntapp.constant.CommandType;
import com.cmw.auntapp.constant.ErrInfo;
import com.cmw.auntapp.core.base.vo.DataResult;
import com.cmw.auntapp.core.util.FastJsonUtil;
import com.cmw.auntapp.core.util.HttpUtil;
import com.cmw.auntapp.core.util.ProgressRequestBody;
import com.cmw.auntapp.core.util.SharedPreferencesUtil;
import com.cmw.auntapp.ui.BaseActivity;
import com.google.android.gms.common.util.CollectionUtils;

import org.w3c.dom.Text;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import static com.cmw.auntapp.constant.CommandType.AUTH_FAIL;
import static com.cmw.auntapp.constant.CommandType.LOCAL_ERR;
import static com.cmw.auntapp.constant.CommandType.UPLOAD;
import static com.cmw.auntapp.constant.Constant.HTTP_READ_TIME_OUT_KEY;
import static com.cmw.auntapp.constant.Constant.HTTP_WRITE_TIME_OUT_KEY;
import static com.cmw.auntapp.constant.Constant.NO_USER_AUTH_TOKEN_KEY;
import static com.cmw.auntapp.constant.Constant.NO_USER_AUTH_TOKEN_VAL_YES;
import static com.cmw.auntapp.constant.Constant.SHOW_LOADING_KEY;
import static com.cmw.auntapp.constant.Constant.SHOW_LOADING_YES;
import static com.cmw.auntapp.constant.Constant.USER_RNAME_KEY;
import static com.cmw.auntapp.constant.Constant.USER_USERAUTHTOKEN_KEY;

/**
 * @desc: 持久化基类
 * @author: chengmingwei
 * @date: 2021/4/26 7:47 PM
 * @contact: phone(微信同号):13922111489 / email: 340360491@qq.com
 */
public abstract class BasePresenter<T> implements IPresenter {

    protected static String TAG = "BasePresenter";

    protected Context context;

    protected void init() {
        TAG = this.getClass().getSimpleName();
        context = (BaseActivity)getView();
        HttpUtil.setContext(context);
    }

    protected String getTag() {
        return this.getClass().getSimpleName();
    }

    @Override
    public Context getContext() {
        return context;
    }

    public void setContext(Context context){
        TAG = this.getClass().getSimpleName();
        this.context = context;
        HttpUtil.setContext(context);
    }

    protected abstract IBaseView getView();

    /**
     * 后台成功后回调方法
     * @param dataResult
     */
    protected void success(CommandType commandType ,DataResult dataResult) { }
    /**
     * 后台失败后回调方法
     * @param dataResult
     */
    protected void failure(CommandType commandType ,DataResult dataResult) { }

    protected void postBody(String api,T requestData, CommandType commandType) {
        Map<String, String> headers = setUserAuthToken(null, commandType);
        Callback callback = getCallback(commandType);
        postBody(api, headers, requestData, callback);
    }

    /**
     * 文件上传
     * @param api API地址
     * @param params 参数
     * @param file  文件对象
     * @param progressListener 进度监听
     */
    protected void upload(String api, Map<String, String> params, File file, ProgressRequestBody.ProgressListener progressListener) {
        upload(api, params, file, progressListener, UPLOAD);
    }

    /**
     * 文件上传
     * @param api API地址
     * @param params 参数
     * @param file  文件对象
     * @param progressListener 进度监听
     * @param commandType 命令类型
     */
    protected void upload(String api, Map<String, String> params, File file, ProgressRequestBody.ProgressListener progressListener, CommandType commandType) {
        Map<String, String> headers = setUserAuthToken(params, commandType);
        headers.put(HTTP_READ_TIME_OUT_KEY, "300"); // 读请求 超时5分钟
        headers.put(HTTP_WRITE_TIME_OUT_KEY, "300"); // 写 超时5分钟
        Callback callback = getCallback(commandType);
        String url = BaseAPI.getAPI(api);
        getView().loading();
        new Thread(() -> {
            HttpUtil.uploadFile(url, headers, params, file, progressListener, callback);
        }).start();
    }

    protected void postBody(String api, T requestData, Callback callback) {
        postBody(api, null, requestData, callback);
    }

    protected void postBody(String api, Map<String,String> head, T requestData, Callback callback) {
        String url = BaseAPI.getAPI(api);
        getView().loading();
        new Thread(() -> {
            String errMsg = HttpUtil.post(url, head, requestData, callback);
            showErrTip(errMsg);
        }).start();

    }

    protected void put(String api, Map<String, String> params, CommandType commandType) {
        Callback callback = getCallback(commandType);
        Map<String, String> headers = setUserAuthToken(params, commandType);
        put(api, headers, params, callback);
    }

    protected void put(String api, Map<String,String> head, Map<String, String> params, Callback callback) {
        String url = BaseAPI.getAPI(api);
        getView().loading();
        new Thread(()->{
            String errMsg =  HttpUtil.put(url, head, params, callback);
            showErrTip(errMsg);
        }).start();
    }

    protected void post(String api, Map<String, String> params, CommandType commandType) {
        Map<String, String> headers = setUserAuthToken(params, commandType);
        Callback callback = getCallback(commandType);
        post(api, headers, params, callback);
    }

    private static CommandType AuthCmdType = null;

    private Callback getCallback(CommandType commandType) {
        Callback callback = new Callback(){
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(getTag(),"onFailure...");
                e.printStackTrace();
                String msg = e.getMessage();
                Log.i(getTag(), msg);
                if (!TextUtils.isEmpty(msg) && msg.indexOf("failed: ETIMEDOUT") != -1) { // 连接到服务器失败
                    msg = "连接到服务端："+BaseAPI.getBaseUrl()+" 超时，请检查网络是否正常或联系客服!";
                    doFailure(msg, LOCAL_ERR);
                    return;
                }
                doFailure(msg, commandType);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                getView().hideLoading();
                int httpCode = response.code();
                String result = response.body().string();
                Log.i(getTag(),"onResponse...,httpCode = "+httpCode);
                Log.i(getTag(),result);
                if (httpCode == 401) {
                    doFailure("用户认证失败，请重新登录!", AUTH_FAIL);
                    return;
                }
                JSONObject resultJson = FastJsonUtil.convertStrToJSONObj(result);
                DataResult dataResult = null;
                if(resultJson.containsKey("status")) {
                    String msg = resultJson.getString("message");
                    dataResult = new DataResult();
                    dataResult.setSuccess(false);
                    dataResult.setCode(DataResult.FAIULE_CODE);
                    dataResult.setMsg(msg);
                } else {
                    dataResult = FastJsonUtil.convertJsonToObj(resultJson, DataResult.class);
                }
                if (null != dataResult && !dataResult.isSuccess()){
                    doFailure(dataResult, commandType);
                    return;
                }
                success(commandType ,dataResult);
                getView().success(commandType, dataResult);
            }
        };
        return callback;
    }

    private void doFailure(DataResult dataResult, CommandType commandType) {
        failure(commandType ,dataResult);
        getView().hideLoading();
        getView().failure(commandType, dataResult);
    }

    private void doFailure(String msg, CommandType commandType) {
        DataResult dataResult = new DataResult();
        dataResult.setCode(DataResult.FAIULE_CODE);
        dataResult.setMsg(msg);
        failure(commandType ,dataResult);
        getView().hideLoading();
        getView().failure(commandType, dataResult);
    }


    protected void post(String api, Map<String, String> params, Callback callback) {
        post(api, null, params, callback);
    }
    protected void post(String api, Map<String,String> head, Map<String, String> params, Callback callback) {
        String url = BaseAPI.getAPI(api);
        getView().loading();
        new Thread(()->{
            String errMsg =  HttpUtil.post(url, head, params, callback);
            showErrTip(errMsg);
        }).start();
    }

    protected void get(String api, CommandType commandType) {
        Map<String, String> headers = setUserAuthToken(null, commandType);
        Callback callback = getCallback(commandType);
        get(api, headers, null, callback);
    }

    protected void get(String api, CommandType commandType, Map<String,String> params) {
        Map<String, String> headers = setUserAuthToken(params, commandType);
        Callback callback = getCallback(commandType);
        get(api, headers, params, callback);
    }

    private Map<String, String> setUserAuthToken(Map<String, String> params, CommandType commandType) {
        if ((null != params && params.size() > 0)
                && (params.get(NO_USER_AUTH_TOKEN_KEY) != null &&
                params.get(NO_USER_AUTH_TOKEN_KEY).equals(NO_USER_AUTH_TOKEN_VAL_YES))) { // 不需要传TOKEN判断
            return null;
        }
        SharedPreferencesUtil util = SharedPreferencesUtil.getInstance(context);
        String userAuthToken = util.getString(USER_USERAUTHTOKEN_KEY);
        if (TextUtils.isEmpty(userAuthToken)) {
            showErrTip(commandType, ErrInfo.UN_USER_AUTH);
            return null;
        }
        Map<String, String> headers = new HashMap<>();
        headers.put(USER_USERAUTHTOKEN_KEY, userAuthToken);
        return headers;
    }

    protected void get(String api, Map<String, String> params) {
        get(api, null, params, null);
    }

    protected void get(String api, Map<String, String> params, Callback callback) {
        get(api, null, params, callback);
    }

    protected void get(String api,Map<String,String> head, Map<String, String> params, Callback callback)  {
        String url = BaseAPI.getAPI(api);
        String showLoading = null;
        if (null != params && params.size() > 0) {
            showLoading = params.get(SHOW_LOADING_KEY);
        }

        if (TextUtils.isEmpty(showLoading) || !showLoading.equals(SHOW_LOADING_YES)) {
            getView().loading();
        }

        new Thread(()->{
            String errMsg = HttpUtil.get(url, head, params, callback);
            showErrTip(errMsg);
        }).start();
    }

    private void showErrTip(CommandType commandType, ErrInfo errInfo) {
        if (errInfo == null) {
            return;
        }
        DataResult dataResult = new DataResult();
        dataResult.setCode(errInfo.getCode());
        dataResult.setMsg(errInfo.getErrMsg());
        getView().failure(commandType, dataResult);
    }

    private void showErrTip(String errMsg) {
        if (TextUtils.isEmpty(errMsg)) {
            return;
        }
        DataResult dataResult = new DataResult();
        dataResult.setCode(DataResult.FAIULE_CODE);
        dataResult.setMsg(errMsg);
        getView().failure(LOCAL_ERR, dataResult);
    }
}
